﻿using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Text;
using System.Xml.Serialization;
using Microsoft.Phone.Shell;
using Newtonsoft.Json;

namespace TradeMeSDK
{
    public interface IDataStore
    {
        bool Backup(string token, object value);
        T Restore<T>(string token);
    }

    public class TransientDataStore : IDataStore
    {
        public bool Backup(string token, object value)
        {
            if (null == value)
                return false;

            var store = PhoneApplicationService.Current.State;
            if (store.ContainsKey(token))
                store[token] = value;
            else
                store.Add(token, value);

            return true;
        }

        public T Restore<T>(string token)
        {
            var store = PhoneApplicationService.Current.State;
            if (!store.ContainsKey(token))
                return default(T);

            return (T)store[token];
        }
    }

    public class PersistentDataStore : IDataStore
    {
        public bool Exists(string token)
        {
            var store = IsolatedStorageSettings.ApplicationSettings;
            return store.Contains(token);
        }

        public bool Backup(string token, object value)
        {
            if (null == value)
                return false;

            var store = IsolatedStorageSettings.ApplicationSettings;
            if (store.Contains(token))
                store[token] = value;
            else
                store.Add(token, value);

            store.Save();
            return true;
        }

        public T Restore<T>(string token)
        {
            var store = IsolatedStorageSettings.ApplicationSettings;
            if (!store.Contains(token))
                return default(T);

            return (T)store[token];
        }
    }

    public class UserDataStore : IDataStore
    {
        private IsolatedStorageFile _store;
        private IsolatedStorageFile Store
        {
            get { return _store ?? (_store = IsolatedStorageFile.GetUserStoreForApplication()); }
        }

        public bool Exists(string token)
        {
            return Store.FileExists(token);
        }

		public void Delete(string token)
		{
			if (Store.FileExists(token))
				Store.DeleteFile(token);
		}

        public bool Backup(string token, object value)
        {
            if (value == null)
                return false;

            using (var filestream = new IsolatedStorageFileStream(token, FileMode.Create, FileAccess.Write, Store))
            {
                using (var sw = new StreamWriter(filestream))
                {
                    using (var writer = new JsonTextWriter(sw))
                    {
                        JsonSerializer serializer = new JsonSerializer();
                        serializer.Serialize(writer, value);
                    }
                }
            }

            return true;
        }

        public T Restore<T>(string token)
        {
            T result;

            try
            {
                using (var filestream = new IsolatedStorageFileStream(token, FileMode.OpenOrCreate, Store))
                {
                    using (var sr = new StreamReader(filestream))
                    {
                        using (var reader = new JsonTextReader(sr))
                        {
                            JsonSerializer serializer = new JsonSerializer();
                            result = serializer.Deserialize<T>(reader);
                        }
                    }
                }
            }
            catch (Exception)
            {
                return default(T);
            }
            return result;
        }
    }

	public class XmlUserDataStore : IDataStore
	{
		private IsolatedStorageFile _store;
		private IsolatedStorageFile Store
		{
			get { return _store ?? (_store = IsolatedStorageFile.GetUserStoreForApplication()); }
		}

		public bool Exists(string token)
		{
			return Store.FileExists(token);
		}

		public void Delete(string token)
		{
			if (Store.FileExists(token))
				Store.DeleteFile(token);
		}

		public bool Backup(string token, object value)
		{
			if (value == null)
				return false;

			using (var filestream = new IsolatedStorageFileStream(token, FileMode.Create, FileAccess.Write, Store))
			{
				using (var sw = new StreamWriter(filestream))
				{
					var transform = new XmlSerializer(value.GetType());
					transform.Serialize(sw, value);
				}
			}

			return true;
		}

		public T Restore<T>(string token)
		{
			try
			{
				using (var filestream = new IsolatedStorageFileStream(token, FileMode.OpenOrCreate, Store))
				{
					using (var sr = new StreamReader(filestream))
					{
						var transform = new XmlSerializer(typeof (T));
						return (T)transform.Deserialize(sr);
					}
				}
			}
			catch (Exception)
			{
				return default(T);
			}
		}
	}


}
